package statistics

import (
	"context"
	"encoding/json"
	"errors"
	"strings"
	"time"
	"unicode/utf8"

	"sale-admin/config/mysql"
	"sale-admin/internal/app/grpc/client"
	"sale-admin/internal/app/grpc/protoc/system_admin"
	"sale-admin/internal/app/web/service"
	"sale-admin/internal/app/web/service/common"
	"sale-admin/internal/app/web/service/robot"
	"sale-admin/internal/dal"
	"sale-admin/internal/dao"
	"sale-admin/internal/define"
	"sale-admin/internal/models"

	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
	"github.com/golang-module/carbon/v2"
	"github.com/samber/lo"
	"gorm.io/gorm"
)

type StatisticsService struct{}

// 首页获取订单统计相关
// 实付金额
// 优惠金额
// 退款金额
// 曝光量
// 转化率
// 支付笔数
func (s StatisticsService) OrderCount(
	ctx context.Context,
	db *gorm.DB,
	merchantID,
	merchantName string,
	paramsShopID *[]string,
) (
	data map[string]interface{},
	err error,
) {
	areas1 := ""
	areas2 := ""
	areas3 := ""
	areas5 := ""
	salesID := ""
	goodsName := ""
	Result := make(map[string]interface{})
	accessTime := time.Now()
	randString := helper.RandString(10)

	// 1、统计今日销售额
	today_amount, _ := OrderStatisticService{}.GetTodayOrder(ctx, db, merchantID, "")
	if today_amount >= 0 {
		Result["today_amount"] = today_amount
	}
	logtime1 := time.Since(accessTime)
	logx.Info(ctx, "order_count_debug_"+randString, logx.Any("logtime1 Milliseconds", logtime1.Milliseconds()))

	// 2、查询近30日销售额
	day_avg_order, _ := OrderStatisticService{}.GetDayAvgOrder(ctx, db, merchantID, "")
	if day_avg_order >= 0 {
		Result["day_avg_order"] = common.Decimal(float64(day_avg_order), 2)
	}
	logtime2 := time.Since(accessTime)
	logx.Info(ctx, "order_count_debug_"+randString, logx.Any("logtime2 Milliseconds", logtime2.Milliseconds()-logtime1.Milliseconds()))

	// 3、实付金额：今日,上周今日,昨日, 近七日实付金额
	pay_amount, err := OrderStatisticService{}.GetDayOrder(ctx, db, merchantID, "")
	if pay_amount != nil {
		Result["pay_amount_day"] = pay_amount["today"]             // 今日
		Result["pay_amount_yesterday"] = pay_amount["yestoday"]    // 昨日
		Result["pay_amount_pre_week"] = pay_amount["week_pre_day"] // 上周今日
	}
	logtime3 := time.Since(accessTime)
	logx.Info(ctx, "order_count_debug_"+randString, logx.Any("logtime3 Milliseconds", logtime3.Milliseconds()-logtime2.Milliseconds()))

	// 4、曝光量：今日, 上周今日 ,昨日, 近七日曝光量
	// 获取当前的商户ID
	var shopIDList = []string{}
	if paramsShopID != nil {
		shopIDList = append(shopIDList, *paramsShopID...)
	}

	// 1.近7天的曝光数据
	start := carbon.Now().SubDays(7).ToDateString() // 06-02
	end := carbon.Now().StartOfDay().ToDateString() // 06-09
	// 获取最近8天的数据（需要往前推一天，所以从近7天变成近8天）
	seven, _, _ := robot.FaceCount{}.GetFaceCount(ctx, db, merchantID, areas3, start, end, salesID, shopIDList, define.DAY, false)
	logtime4 := time.Since(accessTime)
	logx.Info(ctx, "order_count_debug_"+randString, logx.Any("logtime4 Milliseconds", logtime4.Milliseconds()-logtime3.Milliseconds()))
	if len(seven) != 0 {
		Result["ai_day"] = seven[7].FaceCount // day[0].FaceCount
		Result["ai_week_pre"] = seven[0].FaceCount
		Result["ai_pre_day"] = seven[6].FaceCount // day[0].FaceCount
		Result["ai_seven"] = seven
	}

	// 5.商品点击数（今日，昨天，上周今日）
	dayClick, _ := GoodsClickStatistics{}.GetGoodsClick(ctx, db, merchantID, start, end, salesID, shopIDList, define.DAY)
	if len(dayClick) != 0 {
		Result["click_day"] = dayClick[7].ClickNum
		Result["click_week_pre"] = dayClick[0].ClickNum
		Result["click_pre_day"] = dayClick[6].ClickNum
	}
	logtime5 := time.Since(accessTime)
	logx.Info(ctx, "order_count_debug_"+randString, logx.Any("logtime5 Milliseconds", logtime5.Milliseconds()-logtime4.Milliseconds()))

	// -------- 下面这2个可以共同使用 --------
	// 5.【退款】-金额：今日,上周今日,昨日, 近七日实付金额
	// 6.【优惠】-金额：今日,上周今日,昨日, 近七日实付金额
	// refundOrderStatus := "6"
	// refund_day, _ := OrderStatisticService{}.GetOrderCountByDate(ctx, db, merchantID, refundOrderStatus,
	// areas1, areas2, areas3, areas5, start2, end2, salesID, shopIDList)

	// 5.4.近七天
	sevenDay, _, _ := CenterOrderService{}.GetCenterOrderNotCompare(ctx, db, merchantID, shopIDList, salesID, areas1, areas2, areas3, areas5, start, end, goodsName, define.DAY)
	logtime6 := time.Since(accessTime)
	logx.Info(ctx, "order_count_debug_"+randString, logx.Any("logtime6 Milliseconds", logtime6.Milliseconds()-logtime5.Milliseconds()))

	Result["refund_week_day"] = 0
	Result["discount_week_day"] = 0
	Result["refund_pre_day"] = 0
	Result["discount_pre_day"] = 0
	Result["refund_day"] = 0
	Result["discount_day"] = 0
	Result["pay_amount_seven"] = []CenterOrderStruct{}
	Result["refund_seven_day"] = []CenterOrderStruct{}
	Result["discount_seven_day"] = []CenterOrderStruct{}
	if len(sevenDay) != 0 {
		Result["refund_day"] = sevenDay[7].RefundOrderAmount      //今日
		Result["discount_day"] = sevenDay[7].DisCountAmount       //今日
		Result["refund_week_day"] = sevenDay[0].RefundOrderAmount //上周今日
		Result["discount_week_day"] = sevenDay[0].DisCountAmount  //上周今日
		Result["refund_pre_day"] = sevenDay[6].RefundOrderAmount  //昨日
		Result["discount_pre_day"] = sevenDay[6].DisCountAmount   //昨日
		Result["pay_amount_seven"] = sevenDay
		Result["refund_seven_day"] = sevenDay
		Result["discount_seven_day"] = sevenDay

		// 创单数（今日，昨天，上周今日）
		Result["create_day"] = sevenDay[7].DayPayNum
		Result["create_pre_day"] = sevenDay[6].DayPayNum
		Result["create_week_pre"] = sevenDay[0].DayPayNum

		// 支付数（今日，昨天，上周今日）
		Result["pay_day"] = sevenDay[7].SuccessOrderCount
		Result["pay_pre_day"] = sevenDay[6].SuccessOrderCount
		Result["pay_week_pre_day"] = sevenDay[0].SuccessOrderCount
	}
	return Result, err
}

// 异常设备 0曝光0点击0创单
// 返回设备列表
func (s StatisticsService) AbnormalDevice(ctx context.Context, db *gorm.DB, merchantID string, Type int,
	areas1, areas2 string, startTime, endTime int64, page, limit int,
) (data interface{}, err error) {
	data, err = OrderStatisticService{}.GetAbnormalDevice(ctx, db, merchantID, Type, areas1, areas2, startTime, endTime,
		page, limit)
	return
}

// 实时数据 --- 支持机器，商户，商场分页
func (s StatisticsService) ListOpen(ctx context.Context, db *gorm.DB, merchantID, merchantName string, mytype int, startTime, endTime string, page, limit int, salesID string) (data interface{}, totalRobotCount int64, totalCountData interface{}, err error) {
	data, totalRobotCount, totalCountData, err = OrderStatisticService{}.GetStatListV2Open(
		ctx, db, mytype, "1", merchantName, page, limit, salesID, startTime, endTime,
	)
	return
}

func getCompareField(field, areasWhere string) (fields []string) {
	fieldMap := make(map[string]string)
	for _, v := range strings.Split(field, ",") {
		fieldMap[v] = v
	}
	for _, v := range fieldMap {
		if v == "gmv" { // gvm
			fields = append(fields, "ifnull(sum(payment_amount),0) as gmv")
		} else if v == "my_dis_count" { // 优惠金额
			fields = append(fields, "(SELECT 0) as my_dis_count")
		} else if v == "my_payment_amount" { // 实付金额
			fields = append(fields, "(SELECT ifnull(sum(payment_amount),0) AS payment_amount FROM ma_order AS o2 WHERE order_status = 4 "+areasWhere+") as my_payment_amount")
		} else if v == "my_refund_order_amount" { // 退款金额
			fields = append(fields, "(SELECT ifnull(sum(payment_amount),0) FROM ma_order AS o2 WHERE order_status = 6 "+areasWhere+") as my_refund_order_amount")
		} else if v == "facecount" { // 曝光量总计
			fields = append(fields, "(SELECT ifnull(sum(s.face_count),0) FROM ma_ai_service_face_count AS s) AS facecount")
		} else if v == "facecount0" { // 前曝光量
			fields = append(fields, "(SELECT ifnull(sum(s.face_count0),0) FROM ma_ai_service_face_count AS s) AS facecount0")
		} else if v == "facecount1" { // 左曝光量
			fields = append(fields, "(SELECT ifnull(sum(s.face_count1),0) FROM ma_ai_service_face_count AS s) AS facecount1")
		} else if v == "facecount2" { // 右曝光量
			fields = append(fields, "(SELECT ifnull(sum(s.face_count2),0) FROM ma_ai_service_face_count AS s) AS facecount2")
		} else if v == "facecount3" { // 后曝光量
			fields = append(fields, "(SELECT ifnull(sum(s.face_count3),0) FROM ma_ai_service_face_count AS s) AS facecount3")
		} else if v == "click_num" { // 商品点击量
			fields = append(fields, "(SELECT ifnull(sum(g.click_num),0) FROM ma_goods_click AS g) AS click_num")
		} else if v == "my_start_order_count" { // 创单笔数
			fields = append(fields, "(SELECT count(order_id) FROM ma_order AS o2 WHERE o2.order_status IN (1,3,4,5,6)"+areasWhere+") as my_start_order_count")
		} else if v == "my_success_order_count" { // 支付笔数
			fields = append(fields, "(SELECT count(order_id) FROM ma_order AS o2 WHERE order_status = 4 "+areasWhere+") as my_success_order_count")
		} else if v == "my_not_pay_order_count" { // 未支付笔数
			fields = append(fields, "(SELECT count(order_id) FROM ma_order AS o2 WHERE o2.order_status IN (1, 3) "+areasWhere+") as my_not_pay_order_count")
		} else if v == "my_refund_order_count" { // 退款笔数
			fields = append(fields, "(SELECT count(order_id) FROM ma_order AS o2 WHERE order_status = 6 "+areasWhere+" ) as my_refund_order_count")
		} else if v == "click_rate" { // 点击率
			fields = append(fields, "(SELECT ifnull(sum(g.click_num),0) FROM ma_goods_click AS g) AS click_num")
			fields = append(fields, "(SELECT ifnull(sum(s.face_count),0) FROM ma_ai_service_face_count AS s) AS facecount")
		} else if v == "create_rate" { // 创单率
			fields = append(fields, "(SELECT ifnull(sum(g.click_num),0) FROM ma_goods_click AS g) AS click_num")
			fields = append(fields, "(SELECT count(order_id) FROM ma_order AS o2 WHERE o2.order_status IN (1,3,4,5,6)"+areasWhere+") as my_start_order_count")
		} else if v == "pay_rate" { // 支付率
			fields = append(fields, "(SELECT count(order_id) FROM ma_order AS o2 WHERE order_status = 4 "+areasWhere+") as my_success_order_count")
			fields = append(fields, "(SELECT count(order_id) FROM ma_order AS o2 WHERE o2.order_status IN (1,3,4,5,6)"+areasWhere+") as my_start_order_count")
		}
	}
	return
}

// 对比字段
// 指针与omitempty搭配使用，设置某个字段显示某个字段
type CompareFieldStruct struct {
	Areas1              *string  `json:"areas1,omitempty"`
	SalesID             *string  `json:"sales_id,omitempty"`
	ShopID              *string  `json:"shop_id,omitempty"`
	GoodsName           *string  `json:"goods_name,omitempty"`
	GoodsID             *string  `json:"goods_id,omitempty"`
	Gmv                 *float64 `json:"gmv,omitempty"`
	MyDisCount          *float64 `json:"my_dis_count,omitempty"`
	MyPaymentAmount     *float64 `json:"my_payment_amount,omitempty"`
	MyRefundOrderAmount *float64 `json:"my_refund_order_amount,omitempty"`
	Facecount           *float64 `json:"facecount,omitempty"`
	Facecount0          *float64 `json:"facecount0,omitempty"`
	Facecount1          *float64 `json:"facecount1,omitempty"`
	Facecount2          *float64 `json:"facecount2,omitempty"`
	Facecount3          *float64 `json:"facecount3,omitempty"`
	ClickNum            *float64 `json:"click_num,omitempty"`
	MyStartOrderCount   *float64 `json:"my_start_order_count,omitempty"`
	MySuccessOrderCount *float64 `json:"my_success_order_count,omitempty"`
	MyNotPayOrderCount  *float64 `json:"my_not_pay_order_count,omitempty"`
	MyRefundOrderCount  *float64 `json:"my_refund_order_count,omitempty"`
}

// 数据对比 【待优化】
func (s StatisticsService) DataCompare(ctx context.Context, db *gorm.DB, merchantID, startTime, endTime, field,
	areas1, areas2, areas3, goodsID, salesID, shopID string) (Result struct {
	Areas1  []CompareFieldStruct `json:"areas1,omitempty"`
	ShopID  []CompareFieldStruct `json:"shop_id,omitempty"`
	SalesID []CompareFieldStruct `json:"sales_id,omitempty"`
	GoodsID []CompareFieldStruct `json:"goods_id,omitempty"`
}, err error,
) {
	tx := db.Table(models.MaOrder{}.TableName() + " as o")
	areasWhere := ""
	areasWhereTime := ""
	where := "1 = 1 "
	if endTime != "" {
		endTime = carbon.Parse(endTime).ToDateString() + " 23:59:59"
	}
	if startTime != "" && endTime != "" {
		where += " and o.add_time >= '" + startTime + "' and o.add_time <= '" + endTime + "'"
		areasWhereTime += " and (o2.add_time between '" + startTime + "' and '" + endTime + "')"
	}
	// 省级商场
	if areas1 != "" {
		res := []CompareFieldStruct{}
		areasWhere += " and o2.areas1 = o.areas1 " + areasWhereTime
		myfield := getCompareField(field, areasWhere)
		myfield = append(myfield, "o.areas1")
		tx.WithContext(ctx).
			Joins("left join "+models.MaRobot{}.TableName()+" as r on r.sales_id = o.sales_id").
			Where(where).
			Where("o.areas1 in (?)", areas1).
			Select(myfield).
			Group("o.areas1").
			Find(&res)
		Result.Areas1 = res
	}
	// 机器
	if salesID != "" {
		res := []CompareFieldStruct{}
		var salesIDList string
		for _, v := range strings.Split(salesID, ",") {
			salesIDList += "\"" + v + "\","
		}
		salesIDList = strings.TrimSuffix(salesIDList, ",")
		salesWhere := " o.sales_id in (" + salesIDList + ")"
		areasWhere = " and o2.sales_id = o.sales_id " + areasWhereTime
		myfield := getCompareField(field, areasWhere)
		myfield = append(myfield, "o.sales_id")
		tx.WithContext(ctx).
			Joins("left join " + models.MaRobot{}.TableName() + " as r on r.sales_id = o.sales_id").
			Where(where + " and " + salesWhere).
			Select(myfield).
			Group("o.sales_id").
			Find(&res)
		Result.SalesID = res
	}
	// 用户
	if shopID != "" {
		res := []CompareFieldStruct{}
		areasWhere = " and o2.merchant_id = o.merchant_id " + areasWhereTime
		myfield := getCompareField(field, areasWhere)
		myfield = append(myfield, "o.merchant_id as shop_id")
		shopIDList := strings.Split(shopID, ",")
		var shopWhere string
		if merchantID != "1" {
			merchantSon, _ := common.Order{}.GetMerchantChildren(ctx, merchantID, shopIDList)
			shopWhere += " and o.merchant_id in (" + strings.Trim(strings.Join(merchantSon, ",")+","+shopID, ",") + ")"
		} else {
			shopWhere += " and o.merchant_id in (" + shopID + ")"
		}
		shopWhere = strings.TrimPrefix(shopWhere, " and")
		tx.WithContext(ctx).
			Joins("left join " + models.MaRobot{}.TableName() + " as r on r.sales_id = o.sales_id").
			Where(where + " and " + shopWhere).
			Select(myfield).
			Group("o.merchant_id").
			Find(&res)
		Result.ShopID = res
	}
	// 商品
	if goodsID != "" {
		res := []CompareFieldStruct{}
		areasWhere = " AND json_extract_c (o.count_data, '$.GoodsID') = json_extract_c (o2.count_data, '$.GoodsID') " + areasWhereTime
		myfield := getCompareField(field, areasWhere)
		myfield = append(myfield, "json_extract_c (o.count_data, '$.GoodsName') AS goods_name")
		myfield = append(myfield, "json_extract_c (o.count_data, '$.GoodsID') AS goods_id")
		var goodsWhere string
		for _, v := range strings.Split(goodsID, ",") {
			goodsWhere += " or o.count_data like '%\"GoodsID\":\"" + v + "\"%'"
		}
		goodsWhere = strings.TrimPrefix(goodsWhere, " or")
		tx.WithContext(ctx).
			Joins("left join " + models.MaRobot{}.TableName() + " as r on r.sales_id = o.sales_id").
			Where(where + " and (" + goodsWhere + ")").
			Select(myfield).
			Group("goods_name").
			Find(&res)
		for k, v := range res {
			var goodsName string
			json.Unmarshal([]byte("\""+*(v.GoodsName)+"\""), &goodsName)
			res[k].GoodsName = &(goodsName)
		}
		Result.GoodsID = res
	}
	return Result, nil
}

// 首页 订单抵扣金额
func (s StatisticsService) TotalOrderDeduction(ctx context.Context, loginMerchantID string, startTime, endTime int64, merchantID, districtID, locationID string) (data interface{}, err error) {
	shopIDList := strings.Split(merchantID, ",")
	merchantIDList, err1 := common.Order{}.GetMerchantChildren(ctx, loginMerchantID, shopIDList)
	if err1 != nil {
		return
	}

	data, err = dao.NewOrder(ctx, dal.Q).
		WithTimePeriodCond(startTime, endTime).
		WithMerchantIDCond(merchantIDList).
		WithDistrictIDCond(strings.Split(districtID, ",")).
		WithLocationIDCond(strings.Split(locationID, ",")).
		OrderDeduction()
	return
}

// 数据对比
func (s StatisticsService) DataCompareNew(ctx context.Context, loginMerchantID string, startTime, endTime int64,
	merchantID, robotID, locationID, cityID, goodsID, goodsName string) (data interface{}, err error) {
	var groupType int
	var pMerchantID, pRobotID, pLocationID, pCityID string
	if merchantID != "" { // 商户分组
		if len(strings.Split(merchantID, ",")) > 10 {
			return nil, errors.New("样本上限不能超过10个")
		}
		groupType = 2
		pMerchantID = merchantID
	} else if robotID != "" { // 机器分组
		if len(strings.Split(robotID, ",")) > 10 {
			return nil, errors.New("样本上限不能超过10个")
		}
		groupType = 1
		pRobotID = robotID
	} else if locationID != "" { // 商场分组
		if len(strings.Split(locationID, ",")) > 10 {
			return nil, errors.New("样本上限不能超过10个")
		}
		groupType = 3
		pLocationID = locationID
	} else if cityID != "" { // 地区分组
		if len(strings.Split(cityID, ",")) > 10 {
			return nil, errors.New("样本上限不能超过10个")
		}
		groupType = 5
		pCityID = cityID
	} else if goodsID != "" || goodsName != "" { // 商品分组
		if len(strings.Split(goodsID, ",")) > 10 || len(strings.Split(goodsName, ",")) > 10 {
			return nil, errors.New("样本上限不能超过10个")
		}
		goodsIDs := []string{}
		goodsNames := []string{}
		if goodsID != "" {
			goodsIDs = strings.Split(goodsID, ",")
		}
		if goodsName != "" {
			goodsNames = strings.Split(goodsName, ",")
		}
		strings.Split(goodsName, ",")
		return s.GoodsOrder(ctx, loginMerchantID, goodsIDs, goodsNames, startTime, endTime)
	} else {
		return nil, errors.New("样本单元错误")
	}
	// 获取分组的列表及汇总
	list, _, _, err := service.RobotDailyReport{}.DailyReport(ctx, loginMerchantID, startTime, endTime, pMerchantID,
		pRobotID, pLocationID, pCityID, "", groupType, 0 /* dataType */, "" /* orderType */, 0 /* summaryType */, 0, 0)
	// 追加空值
	var MerchantID, RobotName, CityID, LocationID string
	var GMV, PaymentAmount, DiscountAmount, RefundAmount, GiveAmount, Facecount, FacecountFront, FacecountLeft, FacecountRight, GoodsClickRatio, PaidRatio, CreateOrderRatio, RefundRatio float64
	var TotalOrder, TotalPaidOrder, TotalNotPaidOrder, TotalRefundOrder, TotalPaidUser, TotalScreenClick, TotalGoodsClick, TotalOperationDuration, TotalChargingDuration, TotalIdleDuration, TotalTaskDuration, TotalTaskOdometer, TotalTaskRunCount, RobotCount int64
	emptyItem := &models.RobotDailyReport{
		MerchantID: &MerchantID, RobotName: &RobotName, CityID: &CityID, LocationID: &LocationID, GMV: &GMV, PaymentAmount: &PaymentAmount, DiscountAmount: &DiscountAmount, RefundAmount: &RefundAmount, GiveAmount: &GiveAmount, TotalOrder: &TotalOrder, TotalPaidOrder: &TotalPaidOrder, TotalNotPaidOrder: &TotalNotPaidOrder, TotalRefundOrder: &TotalRefundOrder, TotalPaidUser: &TotalPaidUser, TotalScreenClick: &TotalScreenClick, TotalGoodsClick: &TotalGoodsClick, Facecount: &Facecount, FacecountFront: &FacecountFront, FacecountLeft: &FacecountLeft, FacecountRight: &FacecountRight, TotalOperationDuration: &TotalOperationDuration, TotalChargingDuration: &TotalChargingDuration, TotalIdleDuration: &TotalIdleDuration, TotalTaskDuration: &TotalTaskDuration, TotalTaskOdometer: &TotalTaskOdometer, TotalTaskRunCount: &TotalTaskRunCount, GoodsClickRatio: &GoodsClickRatio, PaidRatio: &PaidRatio, CreateOrderRatio: &CreateOrderRatio, RefundRatio: &RefundRatio, RobotCount: &RobotCount,
	}

	if merchantID != "" {
		var merchantExist = []string{}
		for _, v := range list {
			merchantExist = append(merchantExist, *v.MerchantID)
		}
		merchantDiff, _ := lo.Difference(strings.Split(merchantID, ","), merchantExist)
		if len(merchantDiff) > 0 {
			// 系统后台grpc
			SystemAdminClient, systemcClientErr := client.GetSystemAdminClient()
			if systemcClientErr != nil {
				logx.Error(ctx, "connect system admin grpc error", logx.Any("err", systemcClientErr.Error()))
				return
			}
			merchantReq := &system_admin.MerchantNameReq{
				MerchantIds: merchantDiff,
			}
			merchantNameMapRes, err1 := SystemAdminClient.MerchantName(ctx, merchantReq)
			if err1 != nil && merchantNameMapRes != nil && merchantNameMapRes.MerchantNameMap != nil {
				for k, v := range merchantNameMapRes.MerchantNameMap {
					item := *emptyItem
					item.MerchantID = &k
					item.MerchantName = &v
					list = append(list, &item)
				}
			}
		}
	} else if robotID != "" {
		var robotExist = []string{}
		for _, v := range list {
			robotExist = append(robotExist, *v.RobotName)
		}
		robotDiff, _ := lo.Difference(strings.Split(robotID, ","), robotExist)
		if len(robotDiff) > 0 {
			for k := range robotDiff {
				item := *emptyItem
				item.RobotName = &robotDiff[k]
				list = append(list, &item)
			}
		}
	} else if locationID != "" {
		var locationExist = []string{}
		for _, v := range list {
			locationExist = append(locationExist, *v.LocationID)
		}
		locationDiff, _ := lo.Difference(strings.Split(locationID, ","), locationExist)
		if len(locationDiff) > 0 {
			for k := range locationDiff {
				item := *emptyItem
				item.LocationID = &locationDiff[k]
				list = append(list, &item)
			}
		}
	} else if cityID != "" {
		var cityExist = []string{}
		for _, v := range list {
			cityExist = append(cityExist, *v.CityID)
		}
		cityDiff, _ := lo.Difference(strings.Split(cityID, ","), cityExist)
		if len(cityDiff) > 0 {
			for k := range cityDiff {
				item := *emptyItem
				item.CityID = &cityDiff[k]
				list = append(list, &item)
			}
		}
	}
	return list, err
}

// 商品订单统计

type GoodsOrderDataList struct {
	GoodsID           string  `json:"goods_id"`
	GoodsName         string  `json:"goods_name"`
	GMV               float64 `json:"gmv"`                  // gmv
	PaymentAmount     float64 `json:"payment_amount"`       // 实付金额
	DiscountAmount    float64 `json:"discount_amount"`      // 优惠金额
	RefundAmount      float64 `json:"refund_amount"`        // 退款金额
	TotalOrder        int64   `json:"total_order"`          // 创建笔数
	TotalPaidOrder    int64   `json:"total_paid_order"`     // 支付笔数
	TotalNotPaidOrder int64   `json:"total_not_paid_order"` // 未支付笔数
	TotalRefundOrder  int64   `json:"total_refund_order"`   // 退款笔数
	TotalPaidUser     int64   `json:"total_paid_user"`      // 支付人数
	TotalGoodsClick   int64   `json:"total_goods_click"`    // 商品点击数
	DeductionLimit    float64 `json:"deduction_limit"`      // 抵额上限
	DeductionAmount   float64 `json:"deduction_amount"`     // 消耗积分
	PointsAmount      float64 `json:"points_amount"`        // 额购积分
	PointsValue       float64 `json:"points_value"`         // 积分价值
	RobotCount        int64   `json:"robot_count"`          // 设备数
}

func (s StatisticsService) GoodsOrder(ctx context.Context, loginMerchantID string, goodsIDs, goodsNames []string, startTime, endTime int64) (data []GoodsOrderDataList, err error) {
	db := mysql.NewDB()
	if startTime == 0 && endTime == 0 {
		startTime = carbon.Parse(carbon.Now().ToDateString()).ToStdTime().Unix()
		endTime = time.Now().Unix()
	}
	startTimeString := carbon.CreateFromTimestamp(startTime).ToDateString()
	endTimeString := carbon.CreateFromTimestamp(endTime).ToDateTimeString()
	// 获取商品详情map
	var goodsIDNameMap = make(map[string]*models.MaGoodsInfo)
	if len(goodsNames) > 0 {
		goodsIDs = dao.Goods{}.GetGoodsIDByName(ctx, dal.Q, goodsNames...)
	}
	goodsIDNameMap = dao.Goods{}.DetailMap(ctx, dal.Q, goodsIDs)
	// 补充上商品点击数
	goodsClickList, _ := dao.GoodsClick{}.GetGoodsClick(ctx, db, strings.Join(goodsIDs, ","), startTime, endTime)
	goodsClickMap := make(map[string]int64)
	for _, v := range goodsClickList {
		goodsClickMap[v.GoodsID] = v.ClickNum
	}
	// 订单
	// gmv 实付金额 优惠金额 退款金额 抵额上限 消耗积分 额购积分 创建笔数 支付笔数 未支付笔数 退款笔数 支付人数
	var orderList = []struct {
		GoodsID         string  `gorm:"column:goods_id" json:"goods_id"`                   // 商品ID
		GoodsName       string  `gorm:"column:goods_name" json:"goods_name"`               // 商品名称
		RobotName       string  `gorm:"column:robot_name" json:"robot_name"`               // 机器名称
		OutTradeNo      string  `gorm:"column:out_trade_no" json:"out_trade_no"`           // 订单号
		PaymentAmount   float64 `gorm:"column:payment_amount" json:"payment_amount"`       // 实付金额
		DiscountAmount  float64 `gorm:"column:discount_amount" json:"discount_amount"`     // 优惠金额
		OrderStatus     int     `gorm:"column:order_status" json:"order_status"`           // 订单状态
		DeductionLimit  float64 `gorm:"column:deduction_limit" json:"deduction_limit"`     // 抵额上限
		DeductionAmount float64 `gorm:"column:deduction_amount" json:"deduction_amount"`   // 消耗积分
		PointsAmount    float64 `gorm:"column:points_amount" json:"points_amount"`         // 额购积分
		PointsValue     float64 `gorm:"column:points_value" json:"points_value"`           // 积分价值
		TotalGoodsClick int64   `gorm:"column:total_goods_click" json:"total_goods_click"` // 商品点击数
	}{}
	// 获取指定商品的订单列表
	db.Model(&models.MaOrder{}).Where("goods_id IN ?", goodsIDs).
		Where("add_time between ? AND ?", startTimeString, endTimeString).
		Select(
			"goods_id",
			"robot_name",
			"out_trade_no",
			"payment_amount",
			"discount_amount",
			"order_status",
			"deduction_limit",
			"deduction_amount",
			"points_amount",
			"points_value",
		).
		Find(&orderList)
	var goodsMap = make(map[string]GoodsOrderDataList)
	var goodsOrderMap = make(map[string][]string) // 商品对应多个订单
	var goodsRobotMap = make(map[string][]string) // 商品对应多个机器
	for _, v := range orderList {
		goodsOrderMap[v.GoodsID] = append(goodsOrderMap[v.GoodsID], v.OutTradeNo)
		var item GoodsOrderDataList
		if _, ok := goodsMap[v.GoodsID]; ok {
			item = goodsMap[v.GoodsID]
		} else {
			item = GoodsOrderDataList{
				GoodsID:     v.GoodsID,
				GoodsName:   v.GoodsName,
				PointsValue: v.PointsValue,
			}
		}
		item.GMV += v.PaymentAmount                  // gmv
		item.TotalOrder++                            // 创单笔数
		item.DeductionLimit += item.DeductionLimit   // 抵额上限
		item.DeductionAmount += item.DeductionAmount // 消耗积分
		item.PointsAmount += item.PointsAmount       // 额购积分

		if v.OrderStatus == 4 { // 支付完成
			item.PaymentAmount += v.PaymentAmount   // 实付金额
			item.DiscountAmount += v.DiscountAmount // 优惠金额
			item.TotalPaidOrder++                   // 支付笔数
		}
		if v.OrderStatus == 1 || v.OrderStatus == 3 { //未支付
			item.TotalNotPaidOrder++ // 未支付笔数
		}
		if v.OrderStatus == 6 { // 退款
			item.RefundAmount += v.PaymentAmount // 退款金额
			item.TotalRefundOrder++              // 退款笔数
		}
		if _, ok := goodsClickMap[v.GoodsID]; ok {
			item.TotalGoodsClick = goodsClickMap[v.GoodsID]
		}
		if goodsRobots, ok := goodsRobotMap[v.GoodsID]; !ok {
			goodsRobotMap[v.GoodsID] = append(goodsRobotMap[v.GoodsID], v.RobotName)
			item.RobotCount++
		} else {
			if !lo.Contains(goodsRobots, v.RobotName) {
				goodsRobotMap[v.GoodsID] = append(goodsRobotMap[v.GoodsID], v.RobotName)
				item.RobotCount++
			}
		}
		goodsMap[v.GoodsID] = item
	}

	for k, v := range goodsMap {
		// 支付人数
		db.Model(&models.MaWechatRate{}).
			Where("out_trade_no in (?)", goodsOrderMap[k]).
			Select("count(distinct(unique_id)) as pay_num").
			Take(&v.TotalPaidUser)
		v.GMV = common.Decimal(v.GMV, 2)
		v.PaymentAmount = common.Decimal(v.PaymentAmount, 2)
		v.DiscountAmount = common.Decimal(v.DiscountAmount, 2)
		v.RefundAmount = common.Decimal(v.RefundAmount, 2)
		goodsMap[k] = v
	}

	// 填充空值
	for _, v := range goodsIDs {
		var item GoodsOrderDataList
		if _, ok := goodsMap[v]; ok {
			item = goodsMap[v]
		} else {
			item.GoodsID = v
			item.GoodsName = goodsIDNameMap[v].GoodsName1
		}
		data = append(data, item)
	}
	return
}

// 数据对比 -- 模板列表
func (s StatisticsService) DataCompareTemplateList(ctx context.Context, merchantID, userID string) (data []*models.DataCompareTemplate, count int64, err error) {
	data, count, err = dao.DataCompareTemplate{}.List(ctx, dal.Q, merchantID, userID)
	return
}

// 数据对比 -- 模板编辑
func (s StatisticsService) DataCompareTemplateSave(ctx context.Context, merchantID, userID, ID, name, content string) (err error) {
	if utf8.RuneCountInString(name) > 20 {
		return errors.New("模板名称不能超过20个字符")
	}
	if ID == "" { // 新增编辑
		_, count, _ := dao.DataCompareTemplate{}.List(ctx, dal.Q, merchantID, userID)
		if count >= 20 {
			return errors.New("模板最多保存20个")
		}
		err = dao.DataCompareTemplate{}.Create(ctx, dal.Q, merchantID, userID, name, content)
	} else {
		info, err1 := dao.DataCompareTemplate{}.Detail(ctx, dal.Q, ID, merchantID, userID)
		if err1 != nil || info == nil || info.ID == "" {
			err = errors.New("模板不存在")
			return
		}
		err = dao.DataCompareTemplate{}.Update(ctx, dal.Q, merchantID, userID, ID, name, content)
	}
	return
}

// 数据对比 -- 模板删除
func (s StatisticsService) DataCompareTemplateDelete(ctx context.Context, merchantID, userID, ID string) (err error) {
	if ID == "" {
		err = errors.New("ID不能为空")
		return
	}
	info, err1 := dao.DataCompareTemplate{}.Detail(ctx, dal.Q, ID, merchantID, userID)
	if err1 != nil || info == nil || info.ID == "" {
		err = errors.New("模板不存在")
		return
	}
	err2 := dao.DataCompareTemplate{}.Delete(ctx, dal.Q, ID, merchantID, userID)
	if err2 != nil {
		err = errors.New("删除失败")
		return
	}
	return
}
